<?php
/*
 SEARCH.INC.PHP by martin $ 2009/09/23 05:47:06
*/

function search_form($out='', $sess='', $aim, $andor, $category, $display, $sort, $case, $pitch){ // 検索フォーム
 global $DIVISION, $page, $theme_dir;
 $page = isset($page) ? $page : 1;
 $DIVISION['style'] = NL.' <style type="text/css">
   #forBlog1, #forPages1 { 
    color: firebrick; background: url(Images/checked.png) left top no-repeat; padding-left: 1.5em;
    list-style-type: none;
   }
 </style>';
 $body = '
  <script type="text/javascript">/*<![CDATA[*/
   function showFor(aim){
    if(aim===1){
     o("#forPages1").hide();
     o([o("#forBlog1"), o("#forBlog2"), o("#forBlog3")]).show();
    } else {
     o("#forPages1").show();
     o([o("#forBlog1"), o("#forBlog2"), o("#forBlog3")]).hide();
    }
   }
   oParts.start(function(){
    if(o("#forBlog").checked()){
     showFor(1);
     o("#forBlog").$.checked = 1;
    } else {
     showFor(0);
     o("#forPages").$.checked = 1;
    }
    if(o("dl.search-result")){
     window.scrollTo(0, o("h3.search-alert").offset(1) - 200);
    }
   });
  /*]]>*/</script>
  <form action="'.(MODE_STATIC ? ROOT_PATH.'search/' : 'index.php').'" method="post" class="search-form">
   <ul>
    <li>キーワードを入力して下さい．</li>
    <li>複数のときはスペース(全角/半角OK)で区切ります．</li>
    <li>検索対象：
      <label> <input type="radio" name="aim" id="forBlog" value="blog"'.(($aim != 'pages'||$aim == '')?' checked="checked"':'').' onclick="showFor(1);return true;" />ブログ</label>&nbsp;&nbsp;
      <label> <input type="radio" name="aim" id="forPages" value="pages"'.($aim == 'pages' ? ' checked="checked"':'').' onclick="showFor(0);return true;" />ブログの記事以外に作成したページ</label>
    </li>
    <li id="forBlog1">検索語はタイトルか内容・コメント・コメント投稿者名にヒットします．</li>
    <li id="forPages1" style="display:none;">作成したページ（サイドバーのメニューボックスのページ）のみを検索対象とします．</li>
   </ul>
    <div class="hidden">
     <input type="hidden" name="mode" value="search" /><input type="hidden" name="sess" value="'.(($sess == ''||$andor != '')?time():$sess).'" />
    </div>
    <div style="margin:0.7em auto 0.7em 2em;">
    <input type="text" size="60" name="words" value="'.$out.'" class="txt" style="width:60%;" />
    <input type="image" src="'.$theme_dir.'Images/search-button.png" style="vertical-align:top;" alt="Go" title=" これで検索 " />
    <input type="radio" value="and" id="and" name="andor"'.(($andor=='and'||$andor=='')?' checked="checked" ':' ').'/><label for="and">AND</label>
    <input type="radio" value="or" id="or" name="andor"'.($andor=='or'?' checked="checked" ':' ').'/><label for="or">OR</label>
    </div>
    <ul style="margin-left:3em;">
     <li id="forBlog2">検索するカテゴリーの範囲
 ';
 $body .= cat_select(p_('category', 0), 'all|すべて');
 $body .= '</li>
     <li id="forBlog3">結果表示 <select name="result" id="result" style="display:inline;">
      <option value="simple"'.($display=='simple'?' selected="selected"':'').'>タイトルのみ</option>
      <option value="detail"'.(($display=='detail'||$display=='')?' selected="selected"':'').'>本文も一部抜粋する</option></select>
     </li>
     <li>ソート <select name="sort" id="sort" style="display:inline;">
      <option value="score"'.($sort=='score'?' selected="selected"':'').'> ヒット数順  </option>
      <option value="date:late"'.(strstr($sort,'late')?' selected="selected"':'').'> 新しい順 　</option>
      <option value="date:early"'.(strstr($sort,'early')?' selected="selected"':'').'> 古い順 　</option></select>
     </li>
     <li>表示件数 <select name="pitch" id="pitch" style="display:inline;">
      <option value="20"'.($pitch==20?' selected="selected"':'').'> 20　</option>
      <option value="30"'.($pitch==30?' selected="selected"':'').'> 30　</option>
      <option value="50"'.($pitch==50?' selected="selected"':'').'> 50　</option></select>
     </li>
     <li>アルファベットの大文字・小文字の区別
      <input type="radio" value="sens" id="sens" name="case"'.($case=='sens'?' checked="checked" ':' ').'/><label for="sens">する</label>
      <input type="radio" value="ignore" id="ignore" name="case"'.(($case=='ignore'||$case=='')?' checked="checked" ':' ').'/><label for="ignore">しない</label>
     </li>
     </ul>
  </form><!--end search_form-->
 ';
 return $DIVISION['body'] = $body;
}

function do_search(){ // キーワード検索
 global $mb, $apres, $sess, $page, $PAGES_LIST, $DIVISION;
 $MIN = 5; //セッションの持続時間(分)
 $header = $nav = $body = '';
 $sess = !empty($sess) ? $sess : (v_('sess') != '' ? v_('sess') : time());
 $_words = p_('words') != '' ? p_('words') : '';
 $AND = p_('andor')=='and' ? 1 : 0;
 $aim = p_('aim'); $andor = p_('andor');
 $category = p_('category') == '' ? 'all' : p_('category', 0); $display = p_('result');
 $sort = p_('sort'); $case = p_('case'); $pitch = p_('pitch') == '' ? 20 : p_('pitch');
 
 if(!is_numeric($page) || !is_numeric($sess)) exit('ppBlog::Bad Request!');
 
 $results = array();
 $RESULTS_CACHE = DB.'sess_'.$sess;

 if(is_file($RESULTS_CACHE)){
  $results = file($RESULTS_CACHE);
  $parts = array_shift($results);
  $_parts = implode("\t", array($_words, $aim, $andor, $category, $display, $sort, $case, $pitch));
  if(!empty($_POST) && (trim($parts) != $_parts)){
   unlink(PATH.$RESULTS_CACHE);
   return do_search(p_('words'));
  }
  list($_words, $aim, $andor, $category, $display, $sort, $case, $pitch) = explode("\t", $parts);
  search_form($_words, $sess, $aim, $andor, $category, $display, $sort, $case, $pitch);
 } else {
  search_form($_words, $sess, $aim, $andor, $category, $display, $sort, $case, $pitch);
  $wds = preg_replace(array('|\s+|', '|　|'), '+', $_words);
  if(empty($_POST) && (time() - $sess) > 60 * $MIN){
   return $DIVISION['body'] .= ' <h3 class="search-alert">検索のセッションが切れたようです。再度検索を。</h3>'.NL;
  }
  if($wds==''){
   return $DIVISION['header'] .= ' <h3 class="search-intro">詳細検索</h3>'.NL;
  }
  $words = explode('+', $wds);
  $rsort = strstr($sort, 'early');
  if($aim == 'blog' || $aim == ''){
   if($category=='all'){
    $LINES = get_all_articles('', $rsort);
   } else $LINES = get_articles_by_category($category);
   $LINES_TMP = my_glob("tempLINES", DB);
   rewrite(DB."tempLINES".(count($LINES_TMP)), $LINES);
   $LINES_TMP = my_glob("tempLINES", DB); # again
 
   foreach($LINES_TMP as $lines_tmp){
    $LINES = my_file($lines_tmp);
    foreach($LINES as $line){
     list($id,$cat,$title,$com,) = explode('|', $line);
     $comments = get_cmt_array($id);
     $cmt_info = array_shift($comments);
     $comments = isOwnerLoggedIn() ? $comments : preg_grep("{\|1\|[\r\n]$}", $comments, PREG_GREP_INVERT);
     $_comments = '|$|';
     if($comments!=''){
      $_comments .= implode('$', $comments); // set $ as glue
      $com = trim($com).str_replace(NL,'',$_comments);
     }
     $_line = $title.'|'.strip_tags($com);
     $MATCH = $score = 0;
     foreach ($words as $wd){
      if($case == 'ignore'){
       if(stristr($_line, $wd)===FALSE){
        $MATCH = FALSE;
        if($AND) break 1;
       } else {
        $_line = preg_replace("|($wd)|i", ",,$1,,", $_line);
        $score = count(preg_split("|,,$wd,,|i", $_line)) - 1; /* Thanks, naoK! */
        $MATCH = TRUE;
       }
      } else { // case-sensitive
       if(strstr($_line, $wd)===FALSE){
        $MATCH = FALSE;
        if($AND) break 1;
       } else {
        $_line = str_replace("$wd", ",,$wd,,", $_line);
        $score = count(explode(",,$wd,,", $_line)) - 1;
        $MATCH = TRUE;
       }
      }
     }
     if($MATCH)  $results[] = $score.'|'.$id.'|'.$cat.'|'.$_line;
    }
    unlink(PATH.$lines_tmp); # delete temporay file
   } # foreach 
   unset($LINES);
  } else { # aim is pages
   include_once (OD.'pages.ini.php');
   $PAGES = preg_replace('{^\d+?\|\d+?\|[^\|]+?\|([^\|]+?)\|[01]\|$}', PAGE_DIR.'\\1'.'.txt', $PAGES_LIST);
   if(is_array($PAGES)){
    $_pages = array();
    foreach ($PAGES as $pageName){
     $_pages[$pageName] = strip_tags(get_file_content($pageName));
    }
    if(!empty($_pages)){
     $MATCH = $score = 0;
     foreach ($_pages as $pageName=>$_page){
      foreach ($words as $wd){
       if($case == 'ignore'){
        if(stristr($_page, $wd)===FALSE){
         $MATCH = FALSE;
         if($AND) break 1;
        } else {
         $_page = preg_replace("|($wd)|i", ",,$1,,", $_page);
         $score = count(preg_split("|,,$wd,,|i", $_page)) - 1; /* Thanks, naoK! */
         $MATCH = TRUE;
        }
       } else { // case-sensitive
        if(strstr($_page, $wd)===FALSE){
         $MATCH = FALSE;
         if($AND) break 1;
        } else {
         $_page = str_replace("$wd", ",,$wd,,", $_page);
         $score = count(explode(",,$wd,,", $_page)) - 1;
         $MATCH = TRUE;
        }
       }
      }
      if($MATCH) $results[] = $score.'|'.$pageName.'|'.$_page;
     }
    }
   }
   unset($pages, $_page);
  }
  if($sort == 'date:late'){
   $results = preg_replace('{^(\d+?)\|(.+)$}', "\\2\t\\1", $results);
   rsort($results, SORT_NUMERIC);
   $results = preg_replace('{^(.+?)\t(\d+)$}', "\\2|\\1", $results);
  } elseif($sort == 'date:early') {
   $results = preg_replace('{^(\d+?)\|(.+)$}', "\\2\t\\1", $results);
   rsort($results, SORT_NUMERIC);
   $results = array_reverse($results);
   $results = preg_replace('{^(.+?)\t(\d+)$}', "\\2|\\1", $results);
  } else rsort($results, SORT_NUMERIC);
  $total = count($results);
  $pages = ceil($total/$pitch);
  if($pages > 1){
   $parts = "$_words\t$aim\t$andor\t$category\t$display\t$sort\t$case\t$pitch";
   array_unshift($results, $parts);
   rewrite($RESULTS_CACHE, $results);
   array_shift($results);
  }
 }
 $total = count($results);
 $pages = ceil($total/$pitch);
 $page = isset($page) ? $page : 1;
 $offset = $pitch * ($page - 1);
 
 $results = array_slice($results, $offset, $pitch);

 if($total==0){
  return $DIVISION['header'] .= '<h3 class="search-alert">１件もヒットしませんでした。違うキーワードで試して下さい。</h3>'.NL;
 } else {
  $DIVISION['header'] .= ' <h3 class="search-intro">詳細検索の結果</h3>'.NL;
  $header = NL.'<h3 class="search-alert">「'.$_words.'」の検索で'.$total.'件ヒットしました。</h3>'.NL;

   # Page Navigation
  $nav = '<div class="weblog-pageNav">';
  $query = MODE_STATIC ? ROOT_PATH.'search/'.$sess.'/' : 'index.php?mode=search&amp;sess='.$sess;
  
  if($page > 1){
   $nav .= '<a class="prev" title="前へ" href="'.$query.(MODE_STATIC ? 'page/' : '&amp;page=').($page - 1).$apres.'">&laquo;前へ</a>';
  }
  for ($i = 1; $i <= $pages; $i++){
   if($i==$page){
    $nav .= '<span class="current">'.$i.'</span>';
   } else {
    $nav .= '<a href="'.$query.(MODE_STATIC ? 'page/' : '&amp;page=').$i.$apres.'">'.$i.'</a>';
   }
  }
  if($page < $pages){
   $nav .= '<a class="next" href="'.$query.(MODE_STATIC ? 'page/' : '&amp;page=').($page + 1).$apres.'" title="次へ">次へ&raquo</a>';
  }
  $nav .= '</div>'.NL;
  if($pages==1) $nav = ''; // とりあえず...
 }
 if($aim == 'blog' || $aim == ''){
  foreach($results as $i=>$output){
   if(strstr($output,'|$|')){
    list($main,$sub) = explode('|$|', $output); // コメント切り離し
   } else {$main = $output; $sub = '';}
   list($score,$id,$cat,$title,$com) = explode('|', $main);
   $body .= showResult($score, ($offset+$i+1), $id, $cat, $title, $com, $sub, $display);
  }
 } else {
  $i = 0;
  foreach($results as $pageName=>$output){
   list($score, $pageName, $page) = explode('|', $output); 
   $body .= showResultPages($score, ($offset+$i+1), $pageName, $page);
   $i++;
  }
 }
 
 foreach (my_glob('sess_', DB) as $_sess){ // clean up
  list(, $time) = explode('_', $_sess);
  if(time() - $time > 60 * $MIN) unlink(PATH.$_sess);
 }
 return $DIVISION['body'] .= $header.NL.$nav.NL.'<dl class="search-result">'.NL.$body.'</dl>'.NL.$nav;
}

function showResult($score, $index, $id, $cat, $title, $com, $cmnt='', $result){
 global $mb, $apres;
 list($cat, $catlink) = trans_cat($cat, TRUE, TRUE);
 $date = date('Y年n月d日H時i分', $id);
 if(strpos($com, 'style]') || strpos($com, 'script]')){
  $com = preg_replace('{(\[style\].+?\[\/style\]|\[script\].+?\[\/script\])}s', '', $com);
 }
 if(strstr($title, ',')){
  $title = str_replace(',,', '$', $title);
  if(strpos($title, ',')){
   list($title, $pm_title) = explode(',', $title);
   $title = str_replace('$', ',,', $title);
   $link = MODE_STATIC ? ROOT_PATH.date('Ym', $id).'-'.$pm_title.EXT_STATIC : 'index.php?UID='.$id;
  } else {
   $link = MODE_STATIC ? ROOT_PATH.$id.EXT_STATIC : 'index.php?UID='.$id;
   $title = str_replace('$', '', $title);
  }
 } else $link = MODE_STATIC ? ROOT_PATH.$id.EXT_STATIC : 'index.php?UID='.$id;
 $title = '<a href="'.$link.'">'.
          preg_replace('{,,(.*?),,}','<span style="background:'.MARKUP.'">$1</span>',$title).
          '</a> ( ヒット数：'.$score.')';
 if($result == 'simple'){
  return '
  <dt class="search-result-hit"><span class="search-result-index">'.$index.'.</span> '.$title.'<span class="cat">'.categoryNav($cat, $catlink).'</span></dt>
   <dd><em>エントリー日時</em>： '.$date.'</dd>
  ';
 }

 $_com = $_cmnt = '';

 if($mb){
  $pos = mb_strpos($com, ',,');
  $_com .= '･･･'.mb_substr($com, ($pos > 50 ? $pos - 50 : 0), 100).'･･･';
 } else {
  $_com .= my_substr($com, 100);
 }
 
 $_com = convert_str_search($_com);
 if(!empty($cmnt)){
  if(strstr($cmnt, ',,')){ // コメントにヒット
   $_cmnt = '<dl class="search-result-comment">
   <dt> コメント</dt>';
   $comments = explode('$', $cmnt);
   
   foreach($comments as $i=>$cm){
    $commnt = '';
    if($i > 0){
     if(!strstr($cm,'|')) continue;
     list($cid, $poster,,$commnt,) = explode("|", $cm);
    }
    if(!strstr($commnt, ',,')) continue;
    $pos = mb_strpos($commnt, ',,');
    $commnt = '･･･'.mb_substr($commnt, ($pos>50?$pos-50:0), 100).'･･･';
    $_cmnt .= '
  <dd>■ <a href="'.(MODE_STATIC ? ROOT_PATH : 'index.php?UID=').$id.'#CID'.$cid.'">'.convert_str_search($poster).'</a></dd>
  <dd>'.convert_str_search($commnt).'</dd>
    ';
   }
   $_cmnt .= ' </dl><!--#comment-div-->'.NL.'</dd>'.NL;
  }
 } else $_cmnt = '';
 $box = '
  <dt class="search-result-hit"><span class="search-result-index">'.$index.'.</span> '.$title.'<span class="cat">'.categoryNav($cat, $catlink).'</span></dt>
   <dd><em>エントリー日時</em>： '.$date.'</dd>
   <dd>'.$_com.'</dd><!--#article-->
 ';
 return ($_cmnt=='') ? $box : str_replace('</dd><!--#article-->','', $box).$_cmnt;
}

function showResultPages($score, $index, $pageLink, $page){
 global $mb, $apres;
 $_page = '';
 if($mb){
  $pos = mb_strpos($page, ',,');
  $_page .= '･･･'.mb_substr($page, ($pos > 50 ? $pos-50 : 0), 100).'･･･';
 } else {
  $_page .= my_substr($page, 100);
 }
 
 $_page = convert_str_search($_page);
 $pageLink = str_replace(array(PAGE_DIR, '.txt'), '', $pageLink);
 $pageName = trans_page($pageLink, FALSE);
 if($pageName == '') return $DIVISION['body'] = '<h3 class="search-alert">NO</h3>';
 $h = '<dt class="search-result-hit"><span class="search-result-index">'.$index.'.</span> '.
  '<a href="'.(MODE_STATIC ? ROOT_PATH.'pages/' : 'index.php?mode=pages&amp;aim=').$pageLink.$apres.'">'.$pageName.'</a> ( ヒット数：'.$score.')</dt>'.NL;
 $h .= '<dd>'.$_page.'</dd>'.NL;
 return $h;
}

function convert_str_search($str){
 $str = preg_replace('{'.V_URL.'}','<a href="$1$2$3">$1$2$3</a>', $str);
 $str = preg_replace('{\[g\](.*?)\[/g\]}i', '$1', $str);
 $str = preg_replace('/(href=["|\'])([^>]*?)(,,)([^>]*?)(,,)([^>]*?)(["|\'])/ie',
                     "''.stripslashes(str_replace(',','','$0')).''",$str);
 $str = preg_replace('/,,(.*?),,/i',' <span style="background:'.MARKUP.'">$1</span>',$str);
 return str_replace('`', '<br />', $str);
}

?>
